package ru.niir.goodfil.db.handlers;

import org.apache.log4j.Logger;
import ru.niir.goodfil.db.Good;
import ru.niir.goodfil.db.Order;
import ru.niir.goodfil.db.OrderItem;
import ru.niir.goodfil.exceptions.ValidationException;
import ru.niir.goodfil.exceptions.WrongHandlerException;
import ru.niir.goodfil.utils.validation.*;

/**
 * Обработчик позиций заказов
 *
 * @see ru.niir.goodfil.db.OrderItem позиции заказа
 */
public class OrderItemHandler extends Handler {
    /**
     * Конструктор
     */
    public OrderItemHandler(Goodfil gf) {
        super(OrderItem.class, gf);
    }

    /**
     * Проверка позиции заказа (OrderItem).
     * 1. goodId установлен верно (FK)
     * 2. orderId установлен верно (FK)
     * 3. count > 0 (UNSIGNED)
     * 4. startPrice > 0 (UNSIGNED)
     * 5. manualPrice > startPrice
     * 6. factGiverFromStore >= 0 (UNSIGNED)
     * 7. У товара корректно установлен код соответствия с 1С
     */
    public ValidationResult validate(Object o) {
        assert o != null;
        if (!(o instanceof OrderItem)) throw new WrongHandlerException(klass, o.getClass());

        OrderItem orderItem = (OrderItem) o;

        ValidationResult result = ValidationResult.Ok(OrderItem.class);

        if (!gf.exists(Good.class, orderItem.getGoodId()))
            result.addValidationError(new ValidationError("goodId", "Товар", orderItem.getGoodId(), ValidationProblem.REFERENCE));

        if (!gf.exists(Order.class, orderItem.getOrderId()))
            result.addValidationError(new ValidationError("orderId", "Заказ", orderItem.getOrderId(), ValidationProblem.REFERENCE));

        if (orderItem.getCount() <= 0)
            result.addValidationError(new ValidationError("count", "Кол-во товара", orderItem.getCount(), ValidationProblem.POSITIVE));

        if (orderItem.getStartPrice() <= 0)
            result.addValidationError(new ValidationError("startPrice", "Стартовая цена", orderItem.getStartPrice(), ValidationProblem.POSITIVE));

        if (orderItem.getManualPrice() > 0 && orderItem.getManualPrice() <= orderItem.getStartPrice())
            result.addValidationError(new ValidationError("manualPrice", "Цена, установленная вручную", orderItem.getManualPrice(), ValidationProblem.CUSTOM, "Цена установленная вручную должна быть больше чем изначальная цена"));

        if (orderItem.getFactGivenFromStore() < 0)
            result.addValidationError(new ValidationError("factGivenFromStore", "Выдано со склада", orderItem.getFactGivenFromStore(), ValidationProblem.POSITIVE));

        Good good = gf.getGoodById(orderItem.getGoodId());
        if (good.getC1CodeIsMissing())
            result.addValidationError(new ValidationError("1CCode", "Код соответствия с 1С", good.getId(), ValidationProblem.REFERENCE, "В заказе присутствует товар, для которого не указан код соответствия 1С"));

        return result;
    }

    /**
     * Проверка на то, что позиция заказа может быть доабвлена в заказ.
     * А добавлена она может быть только если заказ еще не достиг статуса OrderState.SAVED
     *
     * @see ru.niir.goodfil.utils.validation.OrderItemCreationFailureType причины, по которым позиция заказа не может быть добавлена в заказ
     */
    public CreateCheckResult createCheck(Object o) throws ValidationException {
        assert o != null;
        if (!(o instanceof OrderItem)) throw new WrongHandlerException(klass, o.getClass());

        OrderItem orderItem = (OrderItem) o;

        if (!gf.exists(Order.class, orderItem.getOrderId()))
            throw new ValidationException(OrderItem.class, "orderId", "Заказ", orderItem.getOrderId(), ValidationProblem.REFERENCE);

        Order order = (Order) gf.get(Order.class, orderItem.getOrderId());
        if (!order.getOrderStateIsPreSaved())
            return CreateCheckResult.Error(klass, OrderItemCreationFailureType.ORDER_IS_SAVED);

        return CreateCheckResult.Ok(klass);
    }

    @Override
    public void preUpdate(Object o) {
        OrderItem orderItem = (OrderItem) o;
        OrderItem oldOrderItem = (OrderItem) gf.getOrderItemById(orderItem.getId());
        Logger logger = Logger.getLogger("OrderItemManualPriceChange");
        if (orderItem.getManualPrice() != oldOrderItem.getManualPrice()) {
            StringBuilder sb = new StringBuilder();
            sb.append("ORDER ITEM " + orderItem.getId() + " MANUAL PRICE CHANGED FROM " + oldOrderItem.getManualPrice() + " TO " + orderItem.getManualPrice());
            sb.append(" (order: " + orderItem.getOrderId() + ", ");
            sb.append("user: " + String.valueOf(gf.getUsername()) + ", ");
            sb.append("from: OrderItemHandler.preUpdate)");
            logger.debug(sb.toString());
        }
    }
}
